package org.nstack.header.network.l3;

import org.nstack.header.network.service.NetworkServiceL3NetworkRefInventory;
import org.nstack.header.configuration.PythonClassInventory;
import org.nstack.header.network.l2.L2NetworkInventory;
import org.nstack.header.query.*;
import org. nstack.header.query.*;
import org.nstack.header.search.Inventory;
import org.nstack.header.vm.VmNicInventory;
import org.nstack.header.zone.ZoneInventory;

import javax.persistence.JoinColumn;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


@Inventory(mappingVOClass = L3NetworkVO.class)
@PythonClassInventory
@ExpandedQueries({
        @ExpandedQuery(expandedField = "zone", inventoryClass = ZoneInventory.class,
                foreignKey = "zoneUuid", expandedInventoryKey = "uuid"),
        @ExpandedQuery(expandedField = "l2Network", inventoryClass = L2NetworkInventory.class,
                foreignKey = "l2NetworkUuid", expandedInventoryKey = "uuid"),
        @ExpandedQuery(expandedField = "vmNic", inventoryClass = VmNicInventory.class,
                foreignKey = "uuid", expandedInventoryKey = "l3NetworkUuid"),
        @ExpandedQuery(expandedField = "serviceProviderRef", inventoryClass = NetworkServiceL3NetworkRefInventory.class,
                foreignKey = "uuid", expandedInventoryKey = "l3NetworkUuid", hidden = true)
})
@ExpandedQueryAliases({
        @ExpandedQueryAlias(alias = "serviceProvider", expandedField = "serviceProviderRef.serviceProvider")
})
public class L3NetworkInventory implements Serializable {

    private String uuid;

    private String name;

    private String description;

    private String type;

    private String zoneUuid;

    private String l2NetworkUuid;

    private String state;

    private String dnsDomain;

    private Boolean system;


    private Timestamp createDate;

    private Timestamp lastOpDate;

    @Queryable(mappingClass = L3NetworkDnsInventory.class,
            joinColumn = @JoinColumn(name = "l3NetworkUuid", referencedColumnName = "dns"))
    private List<String> dns;

    @Queryable(mappingClass = IpRangeInventory.class,
            joinColumn = @JoinColumn(name = "l3NetworkUuid"))
    private List<IpRangeInventory> ipRanges;

    @Queryable(mappingClass = NetworkServiceL3NetworkRefInventory.class,
            joinColumn = @JoinColumn(name = "l3NetworkUuid"))
    private List<NetworkServiceL3NetworkRefInventory> networkServices;

    public static L3NetworkInventory valueOf(L3NetworkVO vo) {
        L3NetworkInventory inv = new L3NetworkInventory();
        inv.setUuid(vo.getUuid());
        inv.setCreateDate(vo.getCreateDate());
        inv.setDescription(vo.getDescription());
        inv.setL2NetworkUuid(vo.getL2NetworkUuid());
        inv.setName(vo.getName());
        inv.setType(vo.getType());
        inv.setDnsDomain(vo.getDnsDomain());
        inv.setZoneUuid(vo.getZoneUuid());
        inv.setState(vo.getState().toString());
        for (L3NetworkDnsVO dnsvo : vo.getDns()) {
            inv.getDns().add(dnsvo.getDns());
        }
        inv.setSystem(vo.isSystem());
        inv.setIpRanges(IpRangeInventory.valueOf(vo.getIpRanges()));
        inv.setLastOpDate(vo.getLastOpDate());
        inv.setNetworkServices(NetworkServiceL3NetworkRefInventory.valueOf(vo.getNetworkServices()));
        return inv;
    }

    public static List<L3NetworkInventory> valueOf(Collection<L3NetworkVO> vos) {
        List<L3NetworkInventory> invs = new ArrayList<L3NetworkInventory>(vos.size());
        for (L3NetworkVO vo : vos) {
            invs.add(valueOf(vo));
        }
        return invs;
    }

    public String getDnsDomain() {
        return dnsDomain;
    }

    public void setDnsDomain(String domain) {
        this.dnsDomain = domain;
    }

    public boolean isSystem() {
        return system;
    }

    public void setSystem(boolean system) {
        this.system = system;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getZoneUuid() {
        return zoneUuid;
    }

    public void setZoneUuid(String zoneUuid) {
        this.zoneUuid = zoneUuid;
    }

    public String getL2NetworkUuid() {
        return l2NetworkUuid;
    }

    public void setL2NetworkUuid(String l2NetworkUuid) {
        this.l2NetworkUuid = l2NetworkUuid;
    }


    public List<String> getDns() {
        if (dns == null) {
            dns = new ArrayList<String>();
        }
        return dns;
    }

    public void setDns(List<String> dns) {
        this.dns = dns;
    }

    public Timestamp getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Timestamp createDate) {
        this.createDate = createDate;
    }

    public Timestamp getLastOpDate() {
        return lastOpDate;
    }

    public void setLastOpDate(Timestamp lastOpDate) {
        this.lastOpDate = lastOpDate;
    }

    public List<IpRangeInventory> getIpRanges() {
        return ipRanges;
    }

    public void setIpRanges(List<IpRangeInventory> ipRanges) {
        this.ipRanges = ipRanges;
    }

    public List<NetworkServiceL3NetworkRefInventory> getNetworkServices() {
        return networkServices;
    }

    public void setNetworkServices(List<NetworkServiceL3NetworkRefInventory> networkServices) {
        this.networkServices = networkServices;
    }

    public List<NetworkServiceL3NetworkRefInventory> getNetworkServiceL3NetworkRefByProviderUuid(String providerUuid) {
        if (networkServices == null || networkServices.isEmpty()) {
            return new ArrayList<NetworkServiceL3NetworkRefInventory>(0);
        }

        List<NetworkServiceL3NetworkRefInventory> refs = new ArrayList<NetworkServiceL3NetworkRefInventory>();
        for (NetworkServiceL3NetworkRefInventory ref : networkServices) {
            if (ref.getNetworkServiceProviderUuid().equals(providerUuid)) {
                refs.add(ref);
            }
        }

        return refs;
    }

    public List<String> getNetworkServiceTypesFromProvider(String providerUuid) {
        List<NetworkServiceL3NetworkRefInventory> refs = getNetworkServiceL3NetworkRefByProviderUuid(providerUuid);
        List<String> nwTypes = new ArrayList<String>(refs.size());
        for (NetworkServiceL3NetworkRefInventory ref : refs) {
            nwTypes.add(ref.getNetworkServiceType());
        }
        return nwTypes;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}
